package com.tom.websocket.handler;

import cn.hutool.json.JSONUtil;
import com.tom.enums.MsgTypeEnum;
import com.tom.websocket.UserChannelSession;
import com.tom.websocket.pojo.ChatMsg;
import com.tom.websocket.pojo.DataContent;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.time.LocalDateTime;

/**
 * 创建自定义http 服务响应处理类
 * <pre>
 *  TextWebSocketFrame: 消息的载体
 *
 * </pre>
 *
 * @author zx
 * @date 2024年10月15日 15:42
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    /**
     * 用于记录和管理所有客户端的channel
     */
    public static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * 客户端链接服务端之后 ，打开链接
     *
     * @param ctx
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        //获取客户端channel ,并且放到channelGroup中进行管理(可以作为一个群组)
        String channelId = ctx.channel().id().asLongText();
        System.out.println("客户端链接,channel对应的长ID：" + channelId);
        clients.add(ctx.channel());
    }

    /**
     * 关闭链接
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        //当触发handlerRemoved ,channelGroup会自动移除对应的客户端的channel
        String channelId = ctx.channel().id().asLongText();
        System.out.println("客户端断开,channel对应的长ID：" + channelId);
        clients.remove(ctx.channel());
        String userId = UserChannelSession.getUserIdByChanelId(channelId);
        //移除多余会话
        UserChannelSession.removeUselessChannels(userId,channelId);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {

        //从客户端获取传递过来的消息
        String text = msg.text();
        System.out.println("接收到的数据:" + text);


        //获取当前用户连接的额客户端channel
        Channel currentChanel = ctx.channel();
        String currentChanelId = currentChanel.id().asLongText();
        //String currentChanelShortId = currentChanel.id().asShortText();
        //System.out.println("客户端currentChanelId:"+currentChanelId);
        //System.out.println("客户端currentChanelShortId:"+currentChanelShortId);

        //1.获取客户端发来的消息，并且解析
        DataContent dataContent = JSONUtil.toBean(text, DataContent.class);
        ChatMsg chatMsg = dataContent.getChatMsg();

        String msgText = chatMsg.getMsg();
        //接收者
        String receiverId = chatMsg.getReceiverId();
        String senderId = chatMsg.getSenderId();
        //时间校准,以服务器的时间为准
        LocalDateTime chatTime = chatMsg.getChatTime();
        chatMsg.setChatTime(LocalDateTime.now());
        //获取消息类型，用于判断
        Integer msgType = chatMsg.getMsgType();
        if(msgType == MsgTypeEnum.CONNECT_INIT.type){
            //websocket 初次open的时候,初始化channel会话，把用户id和channel关联起来.
            UserChannelSession.putUserChanelIdRelation(currentChanelId,senderId);
            UserChannelSession.putMultiChannels(senderId,currentChanel);
        }



        //TextWebSocketFrame replayMsg = new TextWebSocketFrame("当前客户端ID为:" + currentChanelId);
        //currentChanel.writeAndFlush(replayMsg);

        //测试向所有客户端群发消息
        //
        //for (Channel channel : clients) {
        //    channel.writeAndFlush(replayMsg);
        //}

        //方式二:
        //clients.writeAndFlush(replayMsg);

        UserChannelSession.outPutMulti();

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        //发生异常之后关闭链接(关闭channel)
        ctx.channel().close();
        //随后从channelGroup中移除对应的channel
        clients.remove(ctx.channel());
        Channel channel = ctx.channel();

        String channelId = channel.id().asLongText();
        String userId = UserChannelSession.getUserIdByChanelId(channelId);
        //移除多余会话
        UserChannelSession.removeUselessChannels(userId,channelId);
    }
}
